"""战斗模型"""

from typing import List, Dict, Any, Optional
from enum import Enum
from pydantic import BaseModel, Field
from .character import Character, CharacterType
from .battlefield import Battlefield
from .skill import Skill, SkillEffect


class BattleStatus(Enum):
    """战斗状态"""
    PREPARING = "preparing"    # 准备中
    ONGOING = "ongoing"        # 进行中
    FINISHED = "finished"      # 已结束


class BattleAction(BaseModel):
    """战斗行动"""
    character_id: str = Field(..., description="行动角色ID")
    skill_id: str = Field(..., description="使用的技能ID")
    target_x: int = Field(..., description="目标X坐标")
    target_y: int = Field(..., description="目标Y坐标")
    effects: List[SkillEffect] = Field(default_factory=list, description="技能效果")
    timestamp: int = Field(..., description="行动时间戳")


class BattleRound(BaseModel):
    """战斗回合"""
    round_number: int = Field(..., description="回合数")
    actions: List[BattleAction] = Field(default_factory=list, description="本回合的行动")
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "round_number": self.round_number,
            "actions": [
                {
                    "character_id": action.character_id,
                    "skill_id": action.skill_id,
                    "target": {"x": action.target_x, "y": action.target_y},
                    "effects": [
                        {
                            "target_id": effect.target_id,
                            "effect_type": effect.effect_type,
                            "value": effect.effect_value,
                            "is_hit": effect.is_hit,
                            "is_crit": effect.is_crit,
                            "is_dodged": effect.is_dodged
                        } for effect in action.effects
                    ],
                    "timestamp": action.timestamp
                } for action in self.actions
            ]
        }


class BattleResult(BaseModel):
    """战斗结果"""
    battle_id: str = Field(..., description="战斗ID")
    status: BattleStatus = Field(..., description="战斗状态")
    winner: Optional[CharacterType] = Field(None, description="获胜方")
    total_rounds: int = Field(0, description="总回合数")
    
    # 战斗参与者
    player_characters: List[Dict[str, Any]] = Field(default_factory=list, description="玩家方角色")
    enemy_characters: List[Dict[str, Any]] = Field(default_factory=list, description="敌方角色")
    
    # 战斗记录
    rounds: List[BattleRound] = Field(default_factory=list, description="回合记录")
    
    # 战场信息
    battlefield_info: Dict[str, Any] = Field(default_factory=dict, description="战场信息")
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "battle_id": self.battle_id,
            "status": self.status.value,
            "winner": self.winner.value if self.winner else None,
            "total_rounds": self.total_rounds,
            "player_characters": self.player_characters,
            "enemy_characters": self.enemy_characters,
            "battlefield": self.battlefield_info,
            "battle_log": [round_data.to_dict() for round_data in self.rounds]
        }


class Battle(BaseModel):
    """战斗类"""
    
    battle_id: str = Field(..., description="战斗ID")
    battlefield: Battlefield = Field(..., description="战场")
    
    # 参战角色
    player_characters: List[Character] = Field(default_factory=list, description="玩家方角色")
    enemy_characters: List[Character] = Field(default_factory=list, description="敌方角色")
    
    # 战斗状态
    status: BattleStatus = Field(BattleStatus.PREPARING, description="战斗状态")
    current_round: int = Field(0, description="当前回合")
    rounds: List[BattleRound] = Field(default_factory=list, description="回合记录")
    
    def add_character(self, character: Character, x: int, y: int) -> bool:
        """添加角色到战斗"""
        if not self.battlefield.place_character(character, x, y):
            return False
            
        if character.character_type == CharacterType.PLAYER:
            self.player_characters.append(character)
        else:
            self.enemy_characters.append(character)
            
        return True
    
    def get_all_characters(self) -> List[Character]:
        """获取所有角色"""
        return self.player_characters + self.enemy_characters
    
    def get_alive_characters(self, character_type: Optional[CharacterType] = None) -> List[Character]:
        """获取存活的角色"""
        all_chars = self.get_all_characters()
        alive_chars = [char for char in all_chars if char.is_alive]
        
        if character_type:
            alive_chars = [char for char in alive_chars if char.character_type == character_type]
            
        return alive_chars
    
    def check_battle_end(self) -> Optional[CharacterType]:
        """检查战斗是否结束"""
        alive_players = self.get_alive_characters(CharacterType.PLAYER)
        alive_enemies = self.get_alive_characters(CharacterType.ENEMY)
        
        if not alive_players:
            return CharacterType.ENEMY
        elif not alive_enemies:
            return CharacterType.PLAYER
        else:
            return None
    
    def execute_action(self, character_id: str, skill: Skill, target_x: int, target_y: int) -> BattleAction:
        """执行战斗行动"""
        # 找到行动角色
        character = None
        for char in self.get_all_characters():
            if char.id == character_id:
                character = char
                break
        
        if not character or not character.is_alive:
            raise ValueError(f"角色 {character_id} 不存在或已死亡")
        
        # 检查目标位置是否有效
        if not self.battlefield.is_valid_position(target_x, target_y):
            raise ValueError(f"目标位置 ({target_x}, {target_y}) 无效")
        
        # 检查是否可以攻击目标位置
        if not skill.can_target_position(character.position_x, character.position_y, target_x, target_y):
            raise ValueError(f"目标位置超出攻击范围")
        
        # 执行技能
        effects = skill.execute(character, target_x, target_y, self.battlefield, self.get_all_characters())
        
        # 创建行动记录
        action = BattleAction(
            character_id=character_id,
            skill_id=skill.id,
            target_x=target_x,
            target_y=target_y,
            effects=effects,
            timestamp=len(self.rounds) * 1000 + len(self.rounds[-1].actions if self.rounds else [])
        )
        
        return action
    
    def start_battle(self) -> None:
        """开始战斗"""
        self.status = BattleStatus.ONGOING
        self.current_round = 1
    
    def next_round(self) -> BattleRound:
        """进入下一回合"""
        if self.status != BattleStatus.ONGOING:
            raise ValueError("战斗未在进行中")
            
        round_obj = BattleRound(round_number=self.current_round)
        self.rounds.append(round_obj)
        self.current_round += 1
        
        return round_obj
    
    def end_battle(self, winner: Optional[CharacterType]) -> BattleResult:
        """结束战斗"""
        self.status = BattleStatus.FINISHED
        
        # 创建战斗结果
        result = BattleResult(
            battle_id=self.battle_id,
            status=self.status,
            winner=winner,
            total_rounds=len(self.rounds),
            player_characters=[char.to_dict() for char in self.player_characters],
            enemy_characters=[char.to_dict() for char in self.enemy_characters],
            rounds=self.rounds,
            battlefield_info=self.battlefield.to_dict()
        )
        
        return result
    
    def get_turn_order(self) -> List[Character]:
        """获取行动顺序（按速度排序）"""
        alive_characters = self.get_alive_characters()
        return sorted(alive_characters, key=lambda x: x.speed, reverse=True)